<template>
  <zh-sheet :round="props.round" :color="props.color" :margin="props.margin" :padding="[0, 0]">
    <slot name="title">
      <zh-sheet v-if="props.title" :color="props.color" :margin="[0, 0]" :padding="[20, 0]">
        <view style="padding-top: 20rpx"></view>
        <zh-text :font-size="fontsize" _class="text-weight-b" :label="props.title"></zh-text>
        <zh-divider></zh-divider>
      </zh-sheet>
    </slot>
    <view class="mt-20"></view>
    <zh-sheet :round="props.round" :color="props.color" :margin="[0, 0]" :padding="[0, 0]">
      <view ref="zhGridRef" class="zh-dragGrid relative fulled" :style="{ height: state.totalH + 'px' }">
        <view
          class="absolute"
          :class="[ani && !disabled ? 'aniOn' : '', state.nowMove_index == index || state.endDrage ? '' : 'tranAni']"
          :style="{
            width: state.itemWidth + 'px',
            height: state.h + 'px',
            left: item.left + 'px',
            top: item.top + 'px',
            zIndex: state.nowMove_index == index ? 5 : 0,
          }"
          v-for="(item, index) in state.listData"
          :key="index"
          :id="'zh-dragGrid-' + index"
          @touchstart="m_start($event, index)"
          @mousedown="m_start($event, index)"
          @touchmove.stop.prevent="m_move($event, index)"
          @mousemove.stop.prevent="m_move($event, index)"
          @touchend="m_end($event, index)"
          @mouseup="m_end($event, index)"
          @longpress="startEdit"
        >
          <slot name="default" :item="item.data">
            <view class="flex-center flex-col" style="width: 100%">
              <view style="width: 100%">
                <zh-badge @click.stop="delitem(item)" v-if="!disabled" color="red" icon="tmicon-times"></zh-badge>
              </view>
              <tm-icon :font-size="45" :name="item.data.icon" :color="item.data.color"></tm-icon>
              <zh-text :font-size="itemFontsize" parentClass="text-align-center" _class="text-weight-b" :label="item.data.title"></zh-text>
            </view>
          </slot>
        </view>
      </view>
    </zh-sheet>
  </zh-sheet>
</template>

<script lang="ts" setup>
/**
 * 宫格拖动排序
 * @property {Number} col = [] 4，一行排列几个
 * @property {Number} width = [] 0，组件宽度，可以不设置默认取父组件宽度
 * @property {Number} itemHeight = [] 120，项目的高度
 * @property {Boolean} ani = [] true，是否开启拖动显示内容抖动动画
 * @property {Boolean} disabled = [] false，是否开启拖动
 * @property {Boolean} longTap = [] true，是否允许长按启动编辑模式。
 * @property {Number} model = [0|1] 0，0图标模式，1方块样式。
 * @property {Array} list = [] []，排序的列表，只要是数组就可，至于内容是什么格式无所谓。
 * @property {Function} change 拖放排序时触发，返回更改后的列表数据。
 * @property {Function} remove 删除一个项目时触发。
 */
import { onMounted, defineProps, ref, reactive, watch, onBeforeMount, nextTick, computed } from 'vue';
import * as u from '@/tool/function/util';
let zhGridRef = ref();
const emits = defineEmits(['update:disabled', 'change', 'remove']);

const props = defineProps({
  round: {
    type: Number,
    default: 2,
  },
  margin: {
    type: Array as PropType<Array<number>>,
    default: () => [0, 0],
  },
  padding: {
    type: Array as PropType<Array<number>>,
    default: () => [0, 0],
  },
  // 背景
  color: {
    type: String,
    default: 'white',
  },
  //几列，一行排几个。
  col: {
    type: Number,
    default: 5,
  },
  //组件宽度，可以不设置默认取父组件宽度
  width: {
    type: Number,
    default: 0,
  },
  //项目的高度
  itemHeight: {
    type: Number,
    default: 120,
  },
  //是否开启拖动显示内容抖动动画
  ani: {
    type: Boolean,
    default: true,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  list: {
    type: Array,
    default: () => [],
  },
  //是否开户长按开始编辑。
  longTap: {
    type: Boolean,
    default: true,
  },
  // 标题
  title: {
    type: String,
    default: '',
  },
  fontsize: {
    type: Number,
    default: 26,
  },
  itemFontsize: {
    type: Number,
    default: 24,
  },
});
const state: any = reactive({
  w: 0,
  h: 0,
  row: 0,
  totalH: 0,
  listData: [],
  itemWidth: 0,
  endDrage: false,
  Drage__id: '', //正在被拖动的id;
  nowMove_index: null, //现在正在移动的索引
  x: 0,
  y: 0,
  prarentTop: 0,
  prarentLeft: 0,
  grid: 0,
  isDrage: false,
});
onMounted(() => {
  nextTick(() => {
    inits();
  });
});
watch(
  () => props.list,
  () => {
    inits();
  },
  { deep: true }
);

function startEdit() {
  if (state.longTap == false) return;
  emits('update:disabled', false);
}
function delitem(item: any) {
  state.listData.splice(item.index, 1);
  emits('remove', item);
  emits('change', state.listData);
}
function m_start(event: any, index: number) {
  //event.preventDefault()
  event.stopPropagation();
  if (state.disabled) return;
  state.nowMove_index = index;
  state.endDrage = false;
  state.isDrage = true;
  if (event.type.indexOf('mouse') == -1 && event.changedTouches.length == 1) {
    var touch = event.changedTouches[0];
    state.y = touch.pageY - event.currentTarget.offsetTop - state.prarentTop;
    state.x = touch.pageX - event.currentTarget.offsetLeft - state.prarentLeft;
  } else {
    state.y = event.pageY - event.currentTarget.offsetTop - state.prarentTop;
    state.x = event.pageX - event.currentTarget.offsetLeft - state.prarentLeft;
  }
  console.log(state.y);
  console.log(state.x);
  // #ifdef MP
  uni.vibrateShort({});
  // #endif
}
function m_move(event: any, index: number) {
  let t = state;
  if (state.disabled) return;
  //event.preventDefault()
  event.stopPropagation();
  if (!state.isDrage) return;
  if (t.endDrage == true) return;

  //当前元素的top位置。
  let chy = 0;
  let chx = 0;
  if (event.type.indexOf('mouse') == -1 && event.changedTouches.length == 1) {
    var touch = event.changedTouches[0];
    chy = touch.pageY - t.y - state.prarentTop;
    chx = touch.pageX - t.x - state.prarentLeft;
    console.log(touch.pageX);
    console.log(t.x);
    console.log(state.prarentLeft);
    console.log('cs：' + chx);
  } else {
    chy = event.pageY - t.y - state.prarentTop;
    chx = event.pageX - t.x - state.prarentLeft;
  }

  t.listData.splice(index, 1, {
    ...t.listData[index],
    top: chy,
    left: chx,
  });
  t.nowMove_index = index;

  const currenit_index = index;
  const currentSort = t.listData[currenit_index].sort;
  const currenit_id = t.listData[currenit_index].__id;

  // 计算当前移动的index.
  let moveIndex = Math.round(chx / t.itemWidth) + Math.round(chy / t.h) * props.col;

  moveIndex = moveIndex < 0 ? 0 : moveIndex;
  moveIndex = moveIndex > t.listData.length - 1 ? t.listData.length - 1 : moveIndex;

  moveIndex = Math.abs(moveIndex);

  index = moveIndex;
  let elList = [...t.listData];
  for (let i = 0; i < elList.length; i++) {
    if (currentSort < moveIndex) {
      if (elList[i].sort > currentSort && elList[i].sort <= moveIndex) {
        elList[i].sort -= 1;
      }
    } else if (currentSort > moveIndex) {
      if (elList[i].sort < currentSort && elList[i].sort >= moveIndex) {
        elList[i].sort += 1;
      }
    }
  }
  elList[currenit_index].sort = moveIndex;
  elList = elList.map((el) => {
    if (el.__id != currenit_id) {
      el.left = (el.sort % props.col) * t.itemWidth;
      el.top = parseInt(el.sort / props.col) * t.h;
    }
    return el;
  });
  t.listData = elList;
}
function m_end(event: any, index: number) {
  if (state.disabled) return;
  let t = state;
  //event.preventDefault()
  event.stopPropagation();
  state.isDrage = false;
  state.endDrage = true;
  if (state.nowMove_index == null) return;
  let elList = [...t.listData];
  elList = setTL(elList);
  elList.sort((a, b) => a.sort - b.sort);
  t.listData = [...elList];
  state.nowMove_index = null;
  moveChange();
}
function moveChange(e, index) {
  if (state.disabled) return;
  //change后修改的数据 。
  const elList = [...state.listData];
  elList.sort((a, b) => a.sort - b.sort - b);
  emits('change', elList);
}
let sys = ref(uni.getSystemInfoSync());
// #ifdef H5
window.addEventListener('resize', () => {
  sys.value = uni.getSystemInfoSync();
});
// #endif
let zhWidth = computed(() => {
  return uni.upx2px(props.width) || zhGridRef.value?.$el.clientWidth || sys.value?.windowWidth;
});

function inits() {
  nextTick(async function () {
    let p = zhGridRef.value?.$el;
    state.grid = props.list.length;
    state.listData = [];
    if (state.grid == 0) {
      return;
    }
    console.log(zhGridRef.value);
    //组件的宽度
    state.w = zhWidth.value;
    state.prarentTop = p.offsetTop;
    state.prarentLeft = p.offsetLeft;
    //项目的高度。
    state.h = uni.upx2px(props.itemHeight);
    //项目的宽度
    state.itemWidth = (state.w - uni.upx2px(props.margin[0]) * 2) / props.col;
    //行数。
    state.row = Math.ceil(state.grid / props.col);

    //总高度
    state.totalH = state.h * state.row;
    //构造一个list宫格列表出来。
    for (let i = 0; i < state.grid; i++) {
      state.listData.push({
        data: props.list[i],
        __id: u.getUid(),
        top: 0,
        left: 0,
        sort: i,
        index: i,
      });
    }
    let list = setTL([...state.listData]);
    console.log(list);
    state.listData = [...list];
  });
}
//计算位置。
function setTL(el) {
  for (let i = 0; i < el.length; i++) {
    el[i].left = (el[i].sort % props.col) * state.itemWidth;
    el[i].top = parseInt(el[i].sort / props.col) * state.h;
  }
  console.log(el);
  return el;
}
</script>

<style lang="scss" scoped>
.aniOn {
  animation: doudong 0.5s linear infinite;
  background: linear-gradient();
  background: -webkit-linear-gradient();
}
.tranAni {
  transition: all 0.15s;
}
@keyframes doudong {
  0% {
    transform: rotate(-2deg) translateX(2rpx) translateY(2rpx);
  }
  25% {
    transform: rotate(0deg) translateX(-2rpx) translateY(-2rpx);
  }
  50% {
    transform: rotate(0deg) translateX(0rpx) translateY(-2rpx);
  }
  75% {
    transform: rotate(0deg) translateX(0rpx) translateY(2rpx);
  }
  100% {
    transform: rotate(-2deg) translateX(2rpx) translateY(2rpx);
  }
}
</style>
